﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Input;

namespace CounterStrikeSourceAimbot
{
    public class AimBot
    {
        public List<PlayerData> AllPlayers;
        public PlayerData CurrentPlayer;
        public bool ValidatePosition;
        public bool OnlyHighlightedUsers;

        public PlayerData FocusingPlayer;

        public AimBot(List<PlayerData> allPlayers, PlayerData currentPlayer)
        {
            AllPlayers = allPlayers;
            CurrentPlayer = currentPlayer;

            
        }

        public void MoveMouse(double deltaX, double deltaY)
        {
            AimBot.POINT pt;

            AimBot.GetCursorPos(out pt);
            var sc = 10;
            AimBot.SetCursorPos(pt.X + (int)(deltaX * sc), pt.Y + (int)(deltaY * sc));
            return;
            var xSign = Math.Sign(deltaX);
            var ySign = Math.Sign(deltaY);


            for (int i = 0; i < Math.Max(Math.Abs(deltaX), Math.Abs(deltaY)); i++)
            {
                Thread.Sleep(1);

                AimBot.SetCursorPos(pt.X + i >= Math.Abs(deltaX) ? 0 : i * xSign, pt.Y + i >= Math.Abs(deltaY) ? 0 : i * ySign);
            }
        }
        public static bool IsAltPressed()
        {
            var states = AimBot.GetKeyboardState();

            var nm = states[0x12];

            var isthat = NativeKeyboard.IsKeyDown(0x12);


            if (isthat)
                Guid.NewGuid();


            return isthat;
        }

        public void BindAsync()
        {
            new Thread(BindSync).Start();
        }

        private void BindSync()
        {
            var rnd = new Random();

            var flag = true;

            var isValidTarget = new Func<PlayerData, bool>(dt =>
            {
                if (dt.Team != CurrentPlayer.Team)
                    return false;

                if (dt.IsDead)
                    return false;

                if (OnlyHighlightedUsers && !dt.IsHighlightedPlayer)
                    return false;

                if(ValidatePosition)
                    if (!dt.HaveValidPosition())
                        return false;

                return true;

            });

            while (true)
            {
                Thread.Sleep(10);

                if (!IsAltPressed())
                {
                    if (FocusingPlayer != null)
                        FocusingPlayer.IsFocused = false;

                    FocusingPlayer = null;
                    continue;
                }


                //detect what user to focus?
                FocusingPlayer =
                    FocusingPlayer ??
                    AllPlayers.FirstOrDefault(
                        isValidTarget);

                if (FocusingPlayer == null)
                    continue;

                FocusingPlayer.IsFocused = true;

                var minErr = double.MaxValue;
                

                var Local = CurrentPlayer;

                foreach (var p in AllPlayers)
                {
                    if (p.IsDead)
                        continue;

                    if (p.Team == CurrentPlayer.Team)
                        continue;

                    var delatX = p.X - Local.X;
                    var delatY = p.Y - Local.Y;
                    var delatZ = p.Z - Local.Z - 20;

                    var direction = MathUtil.GetPitchYaw(delatX, delatY, delatZ);

                    var deltaYa = direction[0] - Local.Yaw;
                    var deltaPich = direction[1] - Local.Pitch;

                    var v = Math.Abs(deltaYa + deltaYa) + Math.Abs(deltaPich + deltaPich);

                    if (v < minErr)
                    {
                        minErr = v;
                        FocusingPlayer = p;
                    }

                    var teta0 = Local.Yaw;
                    var teta1 = direction[0];

                    if (Math.Abs(teta0) > 90 && Math.Abs(teta1) > 90 && teta0 * teta1 < 0)
                        deltaYa = -Math.Sign(teta1 - teta0) * 360.0 + teta1 - teta0;


                }

                if (FocusingPlayer == null)
                    continue;

                

                {
                    var delatX = FocusingPlayer.X - Local.X;
                    var delatY = FocusingPlayer.Y - Local.Y;
                    var delatZ = FocusingPlayer.Z - Local.Z - 20;

                    var direction = MathUtil.GetPitchYaw(delatX, delatY, delatZ);

                    var deltaYa = direction[0] - Local.Yaw;
                    var deltaPich = direction[1] - Local.Pitch;

                    var teta0 = Local.Yaw;
                    var teta1 = direction[0];

                    if (Math.Abs(teta0) > 90 && Math.Abs(teta1) > 90 && teta0 * teta1 < 0)
                        deltaYa = -Math.Sign(teta1 - teta0) * 360.0 + teta1 - teta0;

                    

                    var landa = MathUtil.GetLanda(deltaYa, deltaPich);


                    AimBot.POINT pt;

                    var sc = 0.0;

                    sc = 10 * Math.Pow(landa, 0.001);


                    sc = 0.25 * sc;

                    if (landa > 5)
                        sc = 0.25 * sc;

                    var mousePos = AimBot.GetCursorPos(out pt);




                    var deltax = (sc * -deltaYa);
                    var deltay = (sc * deltaPich);

                    AimBot.SetCursorPos(pt.X + (int)deltax, pt.Y + (int)deltay);
                }
                //
               


            }
        }

        /*
        public void FocusOnPlayer(PlayerData local, PlayerData target)
        {
            Focuser = new PlayerFocuser() {Local = local, Target = target};

            Focuser.BindAsync();

            //throw new NotImplementedException();
        }


        public PlayerFocuser Focuser;
        */
        
        [DllImport("user32.dll")]
        public static extern bool SetCursorPos(int X, int Y);

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int X;
            public int Y;

        }

        /// <summary>
        /// Retrieves the cursor's position, in screen coordinates.
        /// </summary>
        /// <see>See MSDN documentation for further information.</see>
        [DllImport("user32.dll")]
        public static extern bool GetCursorPos(out POINT lpPoint);

        [DllImport("user32.dll", EntryPoint = "GetKeyboardState", SetLastError = true)]
        private static extern bool NativeGetKeyboardState([Out] byte[] keyStates);

        private static bool GetKeyboardState(byte[] keyStates)
        {
            if (keyStates == null)
                throw new ArgumentNullException("keyState");
            if (keyStates.Length != 256)
                throw new ArgumentException("The buffer must be 256 bytes long.", "keyState");
            return NativeGetKeyboardState(keyStates);
        }

        public static byte[] GetKeyboardState()
        {
            byte[] keyStates = new byte[256];
            if (!GetKeyboardState(keyStates))
                throw new Win32Exception(Marshal.GetLastWin32Error());
            return keyStates;
        }

        private static bool AnyKeyPressed()
        {
            byte[] keyState = GetKeyboardState();
            // skip the mouse buttons
            return keyState.Skip(8).Any(state => (state & 0x80) != 0);
        }

        internal static class NativeKeyboard
        {
            /// <summary>
            /// A positional bit flag indicating the part of a key state denoting
            /// key pressed.
            /// </summary>
            private const int KeyPressed = 0x8000;

            /// <summary>
            /// Returns a value indicating if a given key is pressed.
            /// </summary>
            /// <param name="key">The key to check.</param>
            /// <returns>
            /// <c>true</c> if the key is pressed, otherwise <c>false</c>.
            /// </returns>
            public static bool IsKeyDown(int key)
            {
                return (GetKeyState((int)key) & KeyPressed) != 0;
            }

            /// <summary>
            /// Gets the key state of a key.
            /// </summary>
            /// <param name="key">Virtuak-key code for key.</param>
            /// <returns>The state of the key.</returns>
            [System.Runtime.InteropServices.DllImport("user32.dll")]
            private static extern short GetKeyState(int key);
        }
    }

    public class PlayerFocuser
    {
        public PlayerData Local;
        public PlayerData Target { get; set; }

        public bool DoFocus = false;

        public void BindAsync()
        {
            new Thread(BindSync).Start();
        }

        private void BindSync()
        {
            while (true)
            {
                Thread.Sleep(10);

                if (!IsAltPressed())
                    continue;


                //detect what user to focus?


                //
                var delatX = Target.X - Local.X;
                var delatY = Target.Y - Local.Y;
                var delatZ = Target.Z - Local.Z-20;

                var direction = MathUtil.GetPitchYaw(delatX, delatY, delatZ);

                var deltaYa = direction[0] - Local.Yaw;
                var deltaPich = direction[1] - Local.Pitch;

                var teta0 = Local.Yaw;
                var teta1 = direction[0];

                if (Math.Abs(teta0) > 90 && Math.Abs(teta1) > 90 && teta0*teta1 < 0)
                    deltaYa = -Math.Sign(teta1 - teta0)*360.0 + teta1 - teta0;



                var landa =  MathUtil.GetLanda(deltaYa, deltaPich);


                AimBot.POINT pt;

                var sc = 0.0;

                sc = 10 *Math.Pow(landa, 0.001);


                sc = 0.25*sc;

                if (landa > 5)
                    sc = 0.25*sc;

                var mousePos = AimBot.GetCursorPos(out pt);




                var deltax = (sc * -deltaYa);
                var deltay = (sc * deltaPich);

                AimBot.SetCursorPos(pt.X + (int)deltax, pt.Y + (int)deltay);


            }
        }

       

        public void MoveMouse(double deltaX, double deltaY)
        {
            AimBot.POINT pt;

            AimBot.GetCursorPos(out pt);
            var sc = 10;
            AimBot.SetCursorPos(pt.X + (int)(deltaX*sc), pt.Y + (int)(deltaY*sc));
            return;
            var xSign = Math.Sign(deltaX);
            var ySign = Math.Sign(deltaY);

            
            for (int i = 0; i < Math.Max(Math.Abs(deltaX), Math.Abs(deltaY)); i++)
            {
                Thread.Sleep(1);

                AimBot.SetCursorPos(pt.X + i >= Math.Abs(deltaX) ? 0 : i*xSign, pt.Y + i >= Math.Abs(deltaY) ? 0 : i*ySign);
            }
        }
        public static bool IsAltPressed()
        {
            throw new NotImplementedException();
            /*
            var states = AimBot.GetKeyboardState();

            var nm = states[0x12];

            var isthat = NativeKeyboard.IsKeyDown(0x12);


            if (isthat)
                Guid.NewGuid();


            return isthat;
            */
        }

        

    }
}
